use crate::database::AppConfig;
use crate::state::AppState;
use std::sync::Mutex;
use tauri::{AppHandle, Manager, State, Emitter};
use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, Modifiers, Shortcut};

pub fn register_global_shortcuts(app: &AppHandle) -> Result<(), Box<dyn std::error::Error>> {
    // Get app state to read configuration
    let state: State<Mutex<AppState>> = app.state();
    let app_state = state.lock().map_err(|e| format!("Failed to lock state: {}", e))?;
    
    let config = match app_state.database.get_config() {
        Ok(config) => config,
        Err(_) => AppConfig::default(),
        Err(e) => {
            log::error!("Failed to get config for shortcuts: {}", e);
            AppConfig::default()
        }
    };

    // Get shortcuts from config
    let shortcuts = &config.shortcuts;

    // Register toggle window shortcut
    if let Some(toggle_shortcut) = shortcuts.get("toggleWindow").and_then(|v| v.as_str()) {
        if let Ok(shortcut) = parse_shortcut(toggle_shortcut) {
            match app.global_shortcut().register(shortcut) {
                Ok(_) => log::info!("Registered toggle window shortcut: {}", toggle_shortcut),
                Err(e) => log::warn!("Failed to register shortcut '{}': {}. This shortcut may be in use by another application.", toggle_shortcut, e),
            }
        } else {
            log::warn!("Failed to parse toggle window shortcut: {}", toggle_shortcut);
        }
    }

    // Register new item shortcut
    if let Some(new_item_shortcut) = shortcuts.get("newItem").and_then(|v| v.as_str()) {
        if let Ok(shortcut) = parse_shortcut(new_item_shortcut) {
            match app.global_shortcut().register(shortcut) {
                Ok(_) => log::info!("Registered new item shortcut: {}", new_item_shortcut),
                Err(e) => log::warn!("Failed to register shortcut '{}': {}. This shortcut may be in use by another application.", new_item_shortcut, e),
            }
        } else {
            log::warn!("Failed to parse new item shortcut: {}", new_item_shortcut);
        }
    }

    // Register search shortcut
    if let Some(search_shortcut) = shortcuts.get("search").and_then(|v| v.as_str()) {
        if let Ok(shortcut) = parse_shortcut(search_shortcut) {
            match app.global_shortcut().register(shortcut) {
                Ok(_) => log::info!("Registered search shortcut: {}", search_shortcut),
                Err(e) => log::warn!("Failed to register shortcut '{}': {}. This shortcut may be in use by another application.", search_shortcut, e),
            }
        } else {
            log::warn!("Failed to parse search shortcut: {}", search_shortcut);
        }
    }

    Ok(())
}

pub fn unregister_all_shortcuts(app: &AppHandle) -> Result<(), Box<dyn std::error::Error>> {
    app.global_shortcut().unregister_all()?;
    log::info!("Unregistered all global shortcuts");
    Ok(())
}

fn parse_shortcut(shortcut_str: &str) -> Result<Shortcut, Box<dyn std::error::Error>> {
    let parts: Vec<&str> = shortcut_str.split('+').collect();
    let mut modifiers = Modifiers::empty();
    let mut key_code = None;

    for part in parts {
        match part.trim().to_lowercase().as_str() {
            "ctrl" | "cmdorctrl" => {
                #[cfg(target_os = "macos")]
                {
                    modifiers |= Modifiers::META;
                }
                #[cfg(not(target_os = "macos"))]
                {
                    modifiers |= Modifiers::CONTROL;
                }
            }
            "cmd" | "meta" => modifiers |= Modifiers::META,
            "alt" => modifiers |= Modifiers::ALT,
            "shift" => modifiers |= Modifiers::SHIFT,
            "control" => modifiers |= Modifiers::CONTROL,
            key => {
                key_code = Some(parse_key_code(key)?);
            }
        }
    }

    if let Some(code) = key_code {
        Ok(Shortcut::new(Some(modifiers), code))
    } else {
        Err("No key code found in shortcut".into())
    }
}

fn parse_key_code(key: &str) -> Result<Code, Box<dyn std::error::Error>> {
    match key.to_lowercase().as_str() {
        "a" => Ok(Code::KeyA),
        "b" => Ok(Code::KeyB),
        "c" => Ok(Code::KeyC),
        "d" => Ok(Code::KeyD),
        "e" => Ok(Code::KeyE),
        "f" => Ok(Code::KeyF),
        "g" => Ok(Code::KeyG),
        "h" => Ok(Code::KeyH),
        "i" => Ok(Code::KeyI),
        "j" => Ok(Code::KeyJ),
        "k" => Ok(Code::KeyK),
        "l" => Ok(Code::KeyL),
        "m" => Ok(Code::KeyM),
        "n" => Ok(Code::KeyN),
        "o" => Ok(Code::KeyO),
        "p" => Ok(Code::KeyP),
        "q" => Ok(Code::KeyQ),
        "r" => Ok(Code::KeyR),
        "s" => Ok(Code::KeyS),
        "t" => Ok(Code::KeyT),
        "u" => Ok(Code::KeyU),
        "v" => Ok(Code::KeyV),
        "w" => Ok(Code::KeyW),
        "x" => Ok(Code::KeyX),
        "y" => Ok(Code::KeyY),
        "z" => Ok(Code::KeyZ),
        "0" => Ok(Code::Digit0),
        "1" => Ok(Code::Digit1),
        "2" => Ok(Code::Digit2),
        "3" => Ok(Code::Digit3),
        "4" => Ok(Code::Digit4),
        "5" => Ok(Code::Digit5),
        "6" => Ok(Code::Digit6),
        "7" => Ok(Code::Digit7),
        "8" => Ok(Code::Digit8),
        "9" => Ok(Code::Digit9),
        "f1" => Ok(Code::F1),
        "f2" => Ok(Code::F2),
        "f3" => Ok(Code::F3),
        "f4" => Ok(Code::F4),
        "f5" => Ok(Code::F5),
        "f6" => Ok(Code::F6),
        "f7" => Ok(Code::F7),
        "f8" => Ok(Code::F8),
        "f9" => Ok(Code::F9),
        "f10" => Ok(Code::F10),
        "f11" => Ok(Code::F11),
        "f12" => Ok(Code::F12),
        "space" => Ok(Code::Space),
        "enter" => Ok(Code::Enter),
        "escape" => Ok(Code::Escape),
        "tab" => Ok(Code::Tab),
        "backspace" => Ok(Code::Backspace),
        "delete" => Ok(Code::Delete),
        "insert" => Ok(Code::Insert),
        "home" => Ok(Code::Home),
        "end" => Ok(Code::End),
        "pageup" => Ok(Code::PageUp),
        "pagedown" => Ok(Code::PageDown),
        "arrowup" => Ok(Code::ArrowUp),
        "arrowdown" => Ok(Code::ArrowDown),
        "arrowleft" => Ok(Code::ArrowLeft),
        "arrowright" => Ok(Code::ArrowRight),
        _ => Err(format!("Unknown key: {}", key).into()),
    }
}

fn toggle_window_visibility(app: &AppHandle) {
    if let Some(window) = app.get_webview_window("main") {
        match window.is_visible() {
            Ok(true) => {
                let _ = window.hide();
                log::info!("Window hidden via global shortcut");
            }
            Ok(false) => {
                let _ = window.show();
                let _ = window.set_focus();
                log::info!("Window shown via global shortcut");
            }
            Err(e) => {
                log::error!("Failed to get window visibility: {}", e);
            }
        }
    }
}

fn handle_new_item(app: &AppHandle) {
    if let Some(window) = app.get_webview_window("main") {
        let _ = window.show();
        let _ = window.set_focus();
        
        // Emit event to frontend to handle new item creation
        let _ = window.emit("shortcut-new-item", ());
        log::info!("New item shortcut handled");
    }
}

fn handle_search(app: &AppHandle) {
    if let Some(window) = app.get_webview_window("main") {
        let _ = window.show();
        let _ = window.set_focus();
        
        // Emit event to frontend to handle search
        let _ = window.emit("shortcut-search", ());
        log::info!("Search shortcut handled");
    }
}
